#include <google/protobuf/message.h>
#include <google/protobuf/descriptor.h>

#include "bufferSetup.h"

#include <iostream>
#include <sstream>
#include <map>
#include "connect.h"

#include <libpq-fe.h>
#include <libpq/libpq-fs.h>
using namespace std;


////////////////////////////////////////////////////////////////////////////////
// bufferSetup()
//
// Description: This constructor initializes the string variables from the class.
//		Then it creates the PostgresQL database connection object by calling
//		the connect function.
// Inputs: none
// 
//
// Outputs: none
//
// Return: none
/////////////////////////////////////////////////////////////////////////////////
bufferSetup::bufferSetup(int argc, char* argv[]) :
	tableName(""),
	fieldName(""),
	results("")
{
	con = connect(argc, argv);

}

////////////////////////////////////////////////////////////////////////////////
// createTableName()
//
// Description: This function will walk the Google Protocol buffer .proto file,
// 		find the messages, check the database to see if the table exists, else
//		create the table in the database with the message name. Then call the 
//		addTableColumns function to keep walking the proto file 
//		
// Inputs: none
// 
//
// Outputs: none
//
// Return: none
/////////////////////////////////////////////////////////////////////////////////
void bufferSetup::createTableName()
{
    int j = 0;
	for (int i = 0; i < bufferSetup::getFieldCnt(); i++)
	{
		setFieldPtr(i);

		if (getFieldType() == FieldDescriptor::CPPTYPE_MESSAGE)
		{
			fieldName = getFieldName();
			
			//Check to see if table exists
			string tableQuery = ("SELECT * FROM " + fieldName + ";");		
			PGresult * res = PQexec(con, tableQuery.c_str());
			if (PQresultStatus(res) == PGRES_TUPLES_OK) 
			{
			   cout<<"Table already exists, deleting..."<<endl;
			   tableQuery = "DROP TABLE " + fieldName + ";";
			   PQexec(con, tableQuery.c_str());
			}	
			
            string foo("CREATE TABLE " + fieldName + "();");

            commands_.push_back(foo);

			//set table name
			tableName = fieldName;

            setNestedTypePtr(j);
            addTableColumns();	
            
            j++;
		}						
	}
}


////////////////////////////////////////////////////////////////////////////////
// addTableColumns()
//
// Description: This function will continue to walk the Google Protocol buffer 
//		.proto file, and set the column names and tables for the table by
//		creating the SQL commands to ADD COLUMNS
//
// Inputs: none
// 
//
// Outputs: none
//
// Return: none
/////////////////////////////////////////////////////////////////////////////////
void bufferSetup::addTableColumns()
{
    // map the protocol buffer types to their SQL string representations
    map<FieldDescriptor::CppType, string> cpptype_strs;
    cpptype_strs[FieldDescriptor::CPPTYPE_BOOL] = "bool";
    cpptype_strs[FieldDescriptor::CPPTYPE_STRING] = "varchar(80)";
    cpptype_strs[FieldDescriptor::CPPTYPE_INT32] = "int";
    cpptype_strs[FieldDescriptor::CPPTYPE_FLOAT] = "float";
    cpptype_strs[FieldDescriptor::CPPTYPE_DOUBLE] = "double";
    cpptype_strs[FieldDescriptor::CPPTYPE_MESSAGE] = "message";

    for(int i=0; i < bufferSetup::findNestedTokenTypes(); i++)
    {
        bufferSetup::setNestedTokenTypePtr(i);

        string command(
            "ALTER TABLE " + tableName +
            " ADD COLUMN " + bufferSetup::getNestedTokenName() + " " +
            cpptype_strs[bufferSetup::getNestedTokenType()] + ";");

        commands_.push_back(command);
    }
}
